Generics עזאם מרעי המחלקה למדעי המחשב אוניברסיטת בן-גוריון

Similar documents
Generics עזאם מרעי המחלקה למדעי המחשב אוניברסיטת בן-גוריון

Java Generics. Lecture CS1122 Summer 2008

Java Generics Java, summer semester

JAVA V Assertions Java, winter semester

JAVA V Source files Java, winter semester

Subtyping for behaviour?

The collections interfaces

Subtyping for behaviour?

CSE 331 Software Design and Implementation. Lecture 14 Generics 2

CSE 331 Software Design and Implementation. Lecture 14 Generics 2

Outline. 1 Generic Classes. 2 Generics and Subtyping. Generics. Guy Wiener. Generic Classes. Generics and Subtyping

Announcements. Lecture 15 Generics 2. Announcements. Big picture. CSE 331 Software Design and Implementation

CSE 331 Software Design and Implementation. Lecture 15 Generics 2

#Students per correct answers

1.1. Annotations History Lesson - C/C++

11/7/18 JAVA GENERICS. Java Collections. Java Collections. Using Java Collections. Proposals for adding Generics to Java.

Photo credit: Andrew Kennedy JAVA GENERICS

Java. Platforms, etc.

Java. Platforms, etc.

CSCE 314 Programming Languages

PARAMETRIC POLYMORPHISM

Subtyping for behaviour?

Parametric polymorphism and Generics

Lecture Outline. Parametric Polymorphism and Java Generics. Polymorphism. Polymorphism

CSE 331 Software Design & Implementation

CS61B Lecture #25: Java Generics. Last modified: Thu Oct 18 21:04: CS61B: Lecture #25 1

CS61B Lecture #25: Java Generics. Last modified: Thu Oct 19 19:36: CS61B: Lecture #25 1

Generalizing Collection Classes Using Generics with other Java 1.5 Features Integration of Generics with Previous Releases User built generic classes

Software Engineering. Prof. Agostino Poggi

CSE 331. Generics (Parametric Polymorphism)

CSE Lecture 7: Polymorphism and generics 16 September Nate Nystrom UTA

Polymorphic (Generic) Programming in Java

Exercise 8 Parametric polymorphism November 18, 2016

CS108, Stanford Handout #8. Java Generics

Polymorphism. CMSC 330: Organization of Programming Languages. Two Kinds of Polymorphism. Polymorphism Overview. Polymorphism

INF3110 Programming Languages Object Orientation and Types, part II

CSC 172 Data Structures and Algorithms. Lecture 3 Spring 2018 TuTh 3:25 pm 4:40 pm

Java Generics -- an introduction. Based on

Polymorphism (generics)

The list abstract data type defined a number of operations that all list-like objects ought to implement:

CSE 331 Software Design & Implementation

A declaration may appear wherever a statement or expression is allowed. Limited scopes enhance readability.

Announcements. Java Graphics. Exceptions. Java Odds & Ends

Java: exceptions and genericity

CS61B Lecture #24. Today: Java support for generic programming. Readings for today: A Java Reference, Chapter 10.

Advanced Programming - JAVA Lecture 4 OOP Concepts in JAVA PART II

More than you ever wanted to know about. Java Generics. Jeff Meister CMSC 420 Summer 2007

CSE 331 Software Design & Implementation

Problems. Java Generics. Example. Example. Often you need the same behavior for different kind of classes

+ Abstract Data Types

CS 360: Programming Languages Lecture 12: More Haskell

INF3110 Programming Languages Object orientation part II

CS61B Lecture #23. Today: Java support for generic programming. Readings for today: A Java Reference, Chapter 10.

CSE 331 Software Design and Implementation. Lecture 13 Generics 1

Rules and syntax for inheritance. The boring stuff

Collections, Maps and Generics

20 Subclassing and Mutation

Properties of an identifier (and the object it represents) may be set at

CMSC 202. Containers

Stronger vs Weaker (one more time!) Requires more? Promises more? (stricter specifications on what the effects entail)

09/02/2013 TYPE CHECKING AND CASTING. Lecture 5 CS2110 Spring 2013

Announcements. Lecture 14 Generics 1. Announcements. CSE 331 Software Design and Implementation. Leah Perlmutter / Summer 2018

CSE 331 Software Design and Implementation. Lecture 14 Generics 1

generic programming alberto ferrari university of parma

Generics method and class definitions which involve type parameters.

Exam 2. Topics. Preconditions vs. Exceptions. Exam 2 Review. Exam 2 on Thursday, March 29 th. Closed book, closed computer, closed phone

301AA - Advanced Programming [AP-2017]

Binghamton University. CS-140 Fall Dynamic Types

Overriding המחלקה למדעי המחשב עזאם מרעי אוניברסיטת בן-גוריון

Generics with Type Bounds

Type Checking in COOL (II) Lecture 10

Java Brand Generics. Advanced Topics in Java. Khalid Azim Mughal Version date:

Exercise 8 Parametric polymorphism November 17, 2017

Weiss Chapter 1 terminology (parenthesized numbers are page numbers)

CS107 Handout 37 Spring 2007 May 25, 2007 Introduction to Inheritance

23. Generics and Adapters

QUIZ. What is wrong with this code that uses default arguments?

8 Understanding Subtyping

CMSC 202H. Containers and Iterators

Advanced Topics in Java and on Security in Systems Effective Generics. Eirik Eltvik 26 th of February 2007

301AA - Advanced Programming [AP-2017]

Agenda. Objects and classes Encapsulation and information hiding Documentation Packages

DrStrangebrac<E,T> Or how I learned to stop worrying, and love generics...

Programming in C++ Prof. Partha Pratim Das Department of Computer Science and Engineering Indian Institute of Technology, Kharagpur

Section 10 MATERIAL PULLED FROM LAST SECTION AND LAST YEAR S SLIDES

M301: Software Systems & their Development. Unit 4: Inheritance, Composition and Polymorphism

Java 5 New Language Features

Software Paradigms (Lesson 3) Object-Oriented Paradigm (2)

Primitive Java Generic Class

Lecture 13: Subtyping

Modulo I Java Generics

PIC 20A Collections and Data Structures

Java: introduction to object-oriented features

Exam Review. CSE 331 Section 10 12/6/12. Slides by Kellen Donohue with material from Mike Ernst

CS-202 Introduction to Object Oriented Programming

Contents. I. Classes, Superclasses, and Subclasses. Topic 04 - Inheritance

Object-Oriented Design Lecture 11 CS 3500 Spring 2010 (Pucella) Tuesday, Feb 16, 2010

Introducing Generics

Java 1.5 in a Nutshell

COMP6700/2140 Generic Methods

Transcription:

Generics עזאם מרעי המחלקה למדעי המחשב אוניברסיטת בן-גוריון

2 Example List myintlist = new LinkedList(); // 1 myintlist.add(new Integer(0)); // 2 Integer x = myintlist.iterator().next(); // 3

3 Example List myintlist = new LinkedList(); // 1 myintlist.add(new Integer(0)); // 2 Integer x = (Integer) myintlist.iterator().next(); // 3

4 Example List myintlist = new LinkedList(); // 1 myintlist.add(new Integer(0)); // 2 Integer x = (Integer) myintlist.iterator().next(); // 3 The cast on line 3 is annoying. Typically, the programmer knows what kind of data has been placed into a particular list. However, the cast is essential. The compiler can only guarantee that an Object will be returned by the iterator. To ensure the assignment to a variable of type Integer is type safe, the cast is required. Of course, the cast not only introduces clutter. It also introduces the possibility of a run time error. ClassCastException: java.lang.double cannot be cast to java.lang.integer LinkedList myintlist = new LinkedList(); myintlist.add(new Double(0)); Integer x = (Integer) myintlist.iterator().next();

5 Example List myintlist = new LinkedList(); // 1 myintlist.add(new Integer(0)); // 2 Integer x = (Integer) myintlist.iterator().next(); // 3 The cast on line 3 is annoying. Typically, the programmer knows what kind of data has been placed into a particular list. However, the cast is essential. The compiler can only guarantee that an Object will be returned by the iterator. To ensure the assignment to a variable of type Integer is type safe, the cast is required. Of course, the cast not only introduces clutter. It also introduces the possibility of a run time error. What if programmers could actually express their intent, and mark a list as being restricted to contain a particular data type? This is the core idea behind generics.

6 Solution: Generic Classes Generic (Parametric) classes are classes that have Type Parameters A generic class with a concrete type parameter is an instance of the generic class The type parameter can be the type of variables, parameters or return values.

7 Generic Classes in Java Declaring a generic interface or class: interface List<T> { public void add(t t) {...... public class LinkedList<T> implements List<T> { private T[] _data;...

8 Example List myintlist = new LinkedList(); // 1 myintlist.add(new Integer(0)); // 2 Integer x = (Integer) myintlist.iterator().next(); // 3 Solution: USE GENERIC List<Integer> myintlist = new LinkedList<Integer>(); myintlist.add(new Integer(0)); Integer x = myintlist.iterator().next();

9 Example List<Integer> myintlist = new LinkedList<Integer>(); // 1 myintlist.add(new Integer(0)); //2 Integer x = myintlist.iterator().next(); // 3 Notice the type declaration for the variable myintlist. It specifies that this is not just an arbitrary List, but a List of Integer, written List<Integer>. We say that List is a generic interface that takes a type parameter - in this case, Integer. We also specify a type parameter when creating the list object. The other thing to pay attention to is that the cast is gone on line 3. Now, you might think that all we ve accomplished is to move the clutter around However, there is a very big difference here. The compiler can now check the type correctness of the program at compile-time. When we say that myintlist is declared with type List<Integer>, this tells us something about the variable myintlist, which holds true wherever and whenever it is used, and the compiler will guarantee it. In contrast, the cast tells us something the programmer thinks is true at a single point in the code.

10 Generic Classes in Java (cont d) Creating instances of generics: List<Integer> names = new LinkedList<Integer>(); Generic and Concrete types Generic Type: The parametrized type, e.g List Concrete Type: A generic type with a concrete parameter, e.g List<Integer>

11 Defining Simple Generics interface List<T> { public void add(t t) {...... public class LinkedList<T> implements List<T> { private T[] _data;... This should all be familiar, except for the stuff in angle brackets Type parameters can be used throughout the generic declaration, pretty much where you would use ordinary types

12 Defining Simple Generics interface List<T> { public void add(t t) {...... public class LinkedList<T> implements List<T> { private T[] _data;... In the introduction, we saw invocations of the generic type declaration List, such as List<Integer>. In the invocation (usually called a parameterized type), all occurrences of the formal type parameter (E in this case) are replaced by the actual type You might imagine that List<Integer> stands for a version of List where E has been uniformly replaced by Integer: public interface IntegerList { void add(integer x);

13 A helpful, but misleading intuition You might imagine that List<Integer> stands for a version of List where E has been uniformly replaced by Integer It is helpful, because the parameterized type List<Integer> does indeed have methods that look just like this expansion It is misleading, because the declaration of a generic is never actually expanded in this way There aren t multiple copies of the code: not in source, not in binary, not on disk and not in memory This is very different than a C++ template A generic type declaration is compiled once and for all, and turned into a single class file, just like an ordinary class or interface declaration Type parameters are analogous to the ordinary parameters used in methods or constructors Much like a method has formal value parameters that describe the kinds of values it operates on, a generic declaration has formal type parameters When a generic declaration is invoked, the actual type arguments are substituted for the formal type parameters

14 Reminder: Sub-Types and Substitution Sub-Typing defines the class relation B is a subtype of A, marked B A. According to the substitution principle, if B A, then an instance of B can substitute an instance of A. Therefore, it is legal to assign an instance of B b to a reference of A a: a b

15 Covariant Arrays in Java Covariant: a Cat[] is a Animal[] Early versions of Java and C# did not include generics Making arrays invariant rules out useful polymorphic programs boolean equalarrays (Object[] a1, Object[] a2); void shufflearray(object[] a); Covariant arrays leads to problem with writes into the array

16 Covariant Arrays in Java (Cont ) Example: Animal[] an; Cat[] ct = new Cat[30]; an = ct; an[0]= new Animal(); Cat cat = (Cat) an[0]; Runt time error: ArrayStoreException Reading from ct is safely. It is only trying to write to the array that can lead to trouble. Performance problem: each write into an array requires an additional runtime check.

17 Example 2 String[] a = new String[1]; Object[] b = a; b[0] = new A(); Runt time error: ArrayStoreException

18 Generics and Subtyping Let s test our understanding of generics. Is the following code snippet legal? List<String> ls = new ArrayList<String>(); //1 List<Object> lo = ls; //2

19 Generics and Subtyping Let s test our understanding of generics. Is the following code snippet legal? List<String> ls = new ArrayList<String>(); //1 List<Object> lo = ls; //2 Line 1 is certainly legal. The trickier part of the question is line 2. This boils down to the question: is a List of String a List of Object?? Most people s instinct is to answer: sure! Well, take a look at the next few lines: lo.add(new Object()); // 3 String s = ls.get(0); // 4: attempts to assign an Object to a String! The Java compiler will prevent this from happening: line 2 will cause a compile time error

20 G<Child> is not a subtype of G<Parent> If Foo is a subclass of Bar, and G is some generic type declaration, it is not the case that G<Foo> is a subtype of G<Bar>

21 Wildcards Consider writing a routine that prints out all the elements in a collection: Not using generics void printcollection(collection c) { Iterator i = c.iterator(); for (k = 0; k < c.size(); k++) { System.out.println(i.next()); And here is a naive attempt at writing it using generics: Using generics void printcollection(collection<object> c) { for (Object e : c) { System.out.println(e); The problem is that this new version is much less useful than the old one. Whereas the old code could be called with any kind of collection as a parameter, the new code only takes Collection<Object>, which, as we ve just demonstrated, is not a supertype of all kinds of collections!

22 Wildcards? So what is the supertype of all kinds of collections? It s written Collection<?>, that is, a collection whose element type matches anything void printcollection(collection<?> c) { for (Object e : c) { System.out.println(e);? and now, we can call it with any type of collection Notice that inside printcollection(), we can still read elements from c and give them type Object This is always safe, since whatever the actual type of the collection, it does contain objects. Collection<?> c = new ArrayList<String>(); c.add(new Object());

23 Wildcards? So what is the supertype of all kinds of collections? It s written Collection<?>, that is, a collection whose element type matches anything void printcollection(collection<?> c) { for (Object e : c) { System.out.println(e);? and now, we can call it with any type of collection Notice that inside printcollection(), we can still read elements from c and give them type Object This is always safe, since whatever the actual type of the collection, it does contain objects. Collection<?> c = new ArrayList<String>(); c.add(new c.add("a"); Object());

24 Wildcards? So what is the supertype of all kinds of collections? It s written Collection<?>, that is, a collection whose element type matches anything void printcollection(collection<?> c) { for (Object e : c) { System.out.println(e);? and now, we can call it with any type of collection Notice that inside printcollection(), we can still read elements from c and give them type Object This is always safe, since whatever the actual type of the collection, it does contain objects. It isn t safe to add arbitrary objects to it however: Collection<?> c = new ArrayList<String>(); c.add(new Object()); // compile time error

25 Passing data to a wildcard? When the actual type parameter is?, it stands for some unknown type Since we don t know what type that is, we cannot pass anything in The sole exception is null, which is a member of every type On the other hand, given a List<?>, we can call get() and make use of the result The result type is an unknown type, but we always know that it is an object It is therefore safe to assign the result of get() to a variable of type Object or pass it as a parameter where the type Object is expected

26 Bounded Wildcards Consider a simple drawing application that can draw shapes such as rectangles and circles: abstract class Shape { abstract void draw(canvas c); class Circle extends Shape { private int x, y, radius; void draw(canvas c) {... class Rectangle extends Shape { private int x, y, width, height; public void draw(canvas c) {... it would be convenient to have a method in Canvas that draws a list of shapes: public void drawall(list<shape> shapes) { for (Shape s : shapes) { s.draw(this); The type rules say that drawall() can only be called on lists of exactly Shape

27 Bounded Wildcards What we really want is for the method to accept a list of any kind of shape: public void drawall(list<? extends Shape> shapes) {... There is a small but significant difference here: we have replaced the type List<Shape> with List<? extends Shape> Now drawall() will accept lists of any subclass of Shape, so we can now call it on a List<Circle> if we want List<? extends Shape> is an example of a bounded wildcard. The? Stands for an unknown type, just like the wildcards we saw earlier However, in this case, we know that this unknown type is in fact a subtype of Shape. We say that Shape is the upper bound of the wildcard

28 Price of using <? extends Shape> There is, as usual, a price to be paid for the flexibility of using wildcards That price is that it is now illegal to write into shapes in the body of the method For instance, this is not allowed: public void addrectangle(list<? extends Shape> shapes) { shapes.add(0, new Rectangle()); // compile-time error! You should be able to figure out why the code above is disallowed

29 Generic Methods Consider writing a method that takes an array of objects and a collection and puts all objects in the array into the collection Here is a first attempt: static void fromarraytocollection(object[] a, Collection<?> c) { for (Object o : a) { c.add(o); // compile time error By now, you will have learned to avoid the beginner s mistake of trying to use Collection<Object> as the type of the collection parameter You may or may not have recognized that using Collection<?> isn t going to work either Recall that you cannot just shove objects into a collection of unknown type

30 Generic methods The way to do deal with these problems is to use generic methods Just like class declarations, method declarations can be generic - that is, parameterized by one or more type parameters: static <T> void fromarraytocollection(t[] a, Collection<T> c) { for (T o : a) { c.add(o); // correct

31 Type Inference We can call this method with any kind of collection whose element type is a supertype of the element type of the array Object[] oa = new Object[100]; Collection<Object> co = new ArrayList<Object>(); fromarraytocollection(oa, co);// T inferred to be Object Notice that we don t have to pass an actual type argument to a generic method The compiler infers the type argument for us, based on the types of the actual arguments

32 Type Inference We can call this method with any kind of collection whose element type is a supertype of the element type of the array Object[] oa = new Object[100]; Collection<Object> co = new ArrayList<Object>(); fromarraytocollection(oa, co);// T inferred to be Object String[] sa = new String[100]; Collection<String> cs = new ArrayList<String>(); fromarraytocollection(sa, cs); fromarraytocollection (java.lang.string[] a, Collection<java.lang.String> c Notice that we don t have to pass an actual type argument to a generic method The compiler infers the type argument for us, based on the types of the actual arguments

33 Type Inference We can call this method with any kind of collection whose element type is a supertype of the element type of the array Object[] oa = new Object[100]; Collection<Object> co = new ArrayList<Object>(); fromarraytocollection(oa, co);// T inferred to be Object String[] sa = new String[100]; Collection<String> cs = new ArrayList<String>(); fromarraytocollection(sa, cs);// T inferred to be String fromarraytocollection(sa, co);// Notice that we don t have to pass an actual type argument to a generic method The compiler infers the type argument for us, based on the types of the actual arguments

34 Type Inference We can call this method with any kind of collection whose element type is a supertype of the element type of the array Object[] oa = new Object[100]; Collection<Object> co = new ArrayList<Object>(); fromarraytocollection(oa, co);// T inferred to be Object String[] sa = new String[100]; Collection<String> cs = new ArrayList<String>(); fromarraytocollection(sa, cs);// T inferred to be String fromarraytocollection(sa, co);// T inferred to be Object Integer[] ia = new Integer[100]; Float[] fa = new Float[100]; Number[] na = new Number[100]; Collection<Number> cn = new ArrayList<Number>(); fromarraytocollection(ia, cn);// Notice that we don t have to pass an actual type argument to a generic method The compiler infers the type argument for us, based on the types of the actual arguments

35 Type Inference We can call this method with any kind of collection whose element type is a supertype of the element type of the array Object[] oa = new Object[100]; Collection<Object> co = new ArrayList<Object>(); fromarraytocollection(oa, co);// T inferred to be Object String[] sa = new String[100]; Collection<String> cs = new ArrayList<String>(); fromarraytocollection(sa, cs);// T inferred to be String fromarraytocollection(sa, co);// T inferred to be Object Integer[] ia = new Integer[100]; Float[] fa = new Float[100]; Number[] na = new Number[100]; Collection<Number> cn = new ArrayList<Number>(); fromarraytocollection(ia, cn);// T inferred to be Number fromarraytocollection(fa, cn);// T inferred to be Number fromarraytocollection(na, cn);// T inferred to be Number fromarraytocollection(na, co);// T inferred to be Object fromarraytocollection(oa,cs); Notice that we don t have to pass an actual type argument to a generic method The compiler infers the type argument for us, based on the types of the actual arguments

36 Type Inference We can call this method with any kind of collection whose element type is a supertype of the element type of the array Object[] oa = new Object[100]; Collection<Object> co = new ArrayList<Object>(); fromarraytocollection(oa, co);// T inferred to be Object String[] sa = new String[100]; Collection<String> cs = new ArrayList<String>(); fromarraytocollection(sa, cs);// T inferred to be String fromarraytocollection(sa, co);// T inferred to be Object Integer[] ia = new Integer[100]; Float[] fa = new Float[100]; Number[] na = new Number[100]; Collection<Number> cn = new ArrayList<Number>(); fromarraytocollection(ia, cn);// T inferred to be Number fromarraytocollection(fa, cn);// T inferred to be Number fromarraytocollection(na, cn);// T inferred to be Number fromarraytocollection(na, co);// T inferred to be Object fromarraytocollection(oa,cs);

37 Type Inference We can call this method with any kind of collection whose element type is a supertype of the element type of the array Object[] oa = new Object[100]; Collection<Object> co = new ArrayList<Object>(); fromarraytocollection(oa, co);// T inferred to be Object String[] sa = new String[100]; Collection<String> cs = new ArrayList<String>(); fromarraytocollection(sa, cs);// T inferred to be String fromarraytocollection(sa, co);// T inferred to be Object Integer[] ia = new Integer[100]; Float[] fa = new Float[100]; Number[] na = new Number[100]; Collection<Number> cn = new ArrayList<Number>(); fromarraytocollection(ia, cn);// T inferred to be Number fromarraytocollection(fa, cn);// T inferred to be Number fromarraytocollection(na, cn);// T inferred to be Number fromarraytocollection(na, co);// T inferred to be Object fromarraytocollection(oa,cs);//compile-time error fromarraytocollection(na, cs);//

38 When should I use generic methods, and when should I use wildcard types? interface Collection<E> { public <T> boolean containsall(collection<t> c); public <T extends E> boolean addall(collection<t> c);?? interface Collection<E> { public boolean containsall(collection<?> c); public boolean addall(collection<? extends E> c); The type parameter T is used only once. The return type doesn t depend on the type parameter, nor does any other argument to the method This tells us that the type argument is being used for polymorphism; its only effect is to allow a variety of actual argument types to be used at different invocation sites. If that is the case, one should use wildcards. Wildcards are designed to support flexible subtyping, which is what we re trying to express here Generic methods allow type parameters to be used to express dependencies among the types of one or more arguments to a method and/or its return type If there isn t such a dependency, a generic method should not be used

39 It is possible to use both generic methods and wildcards in tandem class Collections { public static <T> void copy(list<t> dest, List<? extends T> src){... Note the dependency between the types of the two parameters Any object copied from the source list, src, must be assignable to the element type T of the destination list, dst So the element type of src can be any subtype of T - we don t care which The signature of copy expresses the dependency using a type parameter, but uses a wildcard for the element type of the second parameter We could have written the signature for this method another way, without using wildcards at all: class Collections { public static <T, S extends T> void copy(list<t> dest, List<S> src){... This is fine, but while the first type parameter is used both in the type of dst and in the bound of the second type parameter, S, S itself is only used once, in the type of src - nothing else depends on it. This is a sign that we can replace S with a wildcard

40 Implementation Generics are implemented by the Java compiler as a front-end conversion called erasure You can (almost) think of it as a source-to-source translation, whereby the generic version is converted to the non-generic version Basically, erasure gets rid of (or erases) all generic type information. All the type information between angle brackets is thrown out, so, for example, a parameterized type like List<String> is converted into List All remaining uses of type variables are replaced by the upper bound of the type variable (usually Object) And, whenever the resulting code isn t type-correct, a cast to the appropriate type is inserted The full details of erasure are beyond our scope, but the simple description we just gave isn t far from the truth

41 Type Erasure Generics were introduced to the Java language to provide tighter type checks at compile time and to support generic programming. To implement generics, the Java compiler applies type erasure to: Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods. Insert type casts if necessary to preserve type safety. Generate bridge methods to preserve polymorphism in extended generic types. Type erasure ensures that no new classes are created for parameterized types; consequently, generics incur no runtime overhead.

42 Erasure and Translation Here, we ve aliased a list of strings and a plain old list: public String loophole(integer x) { List<String> ys = new LinkedList<String>(); List xs = ys; xs.add(x); // compile-time unchecked warning return ys.iterator().next(); We insert an Integer into the list, and attempt to extract a String. This is clearly wrong If we ignore the warning and try to execute this code, it will fail exactly at the point where we try to use the wrong type At run time, this code behaves like: public String loophole(integer x) { List ys = new LinkedList; List xs = ys; xs.add(x); return (String) ys.iterator().next(); // run time error

43 Example (2) public <T> T testgeneric(t x){ List<T> ys = new LinkedList<T>(); System.out.println(x); ys.add(x); return ys.iterator().next(); Integer answer = ts.testgeneric(new Integer(1)); String str = ts.testgeneric( Generic"); public Object testgeneric(object x){ List ys = new LinkedList(); System.out.println(x); ys.add(x); return ys.iterator().next(); Integer answer = (Integer) ts.testgeneric(new Integer(1)); String str = (String) ts.testgeneric( Generic");

44 A Generic Class is Shared by all its Invocations What does the following code fragment print? List <String> l1 = new ArrayList<String>(); List<Integer> l2 = new ArrayList<Integer>(); System.out.println(l1.getClass() == l2.getclass()); You might be tempted to say false, but you d be wrong. It prints true, because all instances of a generic class have the same run-time class, regardless of their actual type parameters. Indeed, what makes a class generic is the fact that it has the same behavior for all of its possible type parameters; the same class can be viewed as having many different types As consequence, the static variables and methods of a class are also shared among all the instances.

45 Casts and InstanceOf Another implication of the fact that a generic class is shared among all its instances, is that it usually makes no sense to ask an instance if it is an instance of a particular invocation of a generic type: Collection cs = new ArrayList<String>(); if (cs instanceof Collection<String>) {... // illegal similarly, Collection<String> cstr = (Collection<String>) cs; // unchecked warning The same is true of type variables: <T> T badcast(t t, Object o) {return (T) o; // unchecked warning Type variables don t exist at run time. This means that they entail no performance overhead in either time nor space, which is nice. Unfortunately, it also means that you can t reliably use them in casts

46 More Fun with Wildcards We ve seen examples where bounded wildcards were useful when reading from a data structure Now consider the inverse, a write-only data structure Flush all elements of the collection and return the last element flushed: public static <T> T writeall(collection<t> coll, Sink<T> snk){ T last; for (T t : coll) { last = t; snk.flush(last); return last;... Sink<Object> s; Collection<String> cs; String str = writeall(cs, s); // illegal call

47 A solution? As written, the call to writeall() is illegal, as no valid type argument can be inferred; neither String nor Object are appropriate types for T, because the Collection element and the Sink element must be of the same type We can fix this by modifying the signature of writeall() as shown below, using a wildcard public static <T> T writeall(collection<? extends T>, Sink<T>){...... String str = writeall(cs, s); // call ok, but wrong return type The call is now legal, but the assignment is erroneous, since the return type inferred is Object because T matches the element type of s, which is Object

48 Lower Bounds The solution is to use a form of bounded wildcard we haven t seen yet: wildcards with a lower bound The syntax <? super T> denotes an unknown type that is a supertype of T It is the dual of the bounded wildcards we ve been using, where we use <? extends T> to denote an unknown type that is a subtype of T public static <T> T writeall(collection<t> coll, Sink<? super T> snk){...... String str = writeall(cs, s); // Yes! Using this syntax, the call is legal, and the inferred type is String, as desired

49 Lower / Upper Bounds = Read / Write permission Upper Bound Marked G<? extends X> A descendant of X Allows to read an instance Lower Bound Marked G<? super Y> An ancestor of Y Allows to write to an instance